package com.jplus.core.mvc;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.jplus.core.utill.JUtil;

/**
 * Request上下文，多例模式 注重上下文容器
 */
public class WebContext {

	private static final String CHARSET = Charset.defaultCharset().name();
	/**
	 * 使每个线程拥有各自的 DataContext 实例
	 */
	private static final ThreadLocal<WebContext> dataContextContainer = new ThreadLocal<WebContext>();

	private HttpServletRequest request;
	private HttpServletResponse response;
	private Map<String, String> restfulParam;

	/**
	 * 初始化
	 */
	public static void init(HttpServletRequest request, HttpServletResponse response) {
		WebContext webContext = new WebContext();
		webContext.request = request;
		webContext.response = response;
		dataContextContainer.set(webContext);
	}

	/**
	 * 销毁【必须】
	 */
	public static void destroy() {
		dataContextContainer.remove();
	}

	public static Map<String, String> getRestfulParam() {
		return getInstance().restfulParam;
	}

	public static void setRestfulParam(Map<String, String> restfulParam) {
		getInstance().restfulParam = restfulParam;
	}

	/**
	 * 获取 DataContext 实例
	 */
	public static WebContext getInstance() {
		return dataContextContainer.get();
	}

	/**
	 * 获取 Request 对象
	 */
	public static HttpServletRequest getRequest() {
		return getInstance().request;
	}

	/**
	 * 获取 Response 对象
	 */
	public static HttpServletResponse getResponse() {
		return getInstance().response;
	}

	/**
	 * 获取 Session 对象
	 */
	public static HttpSession getSession() {
		return getRequest().getSession();
	}

	/**
	 * 获取 Servlet Context 对象
	 */
	public static javax.servlet.ServletContext getServletContext() {
		return getRequest().getServletContext();
	}

	/**
	 * 封装 Request 相关操作
	 */
	public static class Request {

		/**
		 * 将数据放入 Request 中
		 */
		public static void put(String key, Object value) {
			getRequest().setAttribute(key, value);
		}

		/**
		 * 从 Request 中获取数据
		 */
		public static Object get(String key) {
			return getRequest().getAttribute(key);
		}

		/**
		 * 移除 Request 中的数据
		 */
		public static void remove(String key) {
			getRequest().removeAttribute(key);
		}

		/**
		 * 从 Request 中获取所有数据
		 */
		public static Map<String, Object> getAll() {
			Map<String, Object> map = new HashMap<String, Object>();
			Enumeration<String> names = getRequest().getAttributeNames();
			while (names.hasMoreElements()) {
				String name = names.nextElement();
				map.put(name, getRequest().getAttribute(name));
			}
			return map;
		}
	}

	/**
	 * 封装 Response 相关操作
	 */
	public static class Response {

		/**
		 * 将数据放入 Response 中
		 */
		public static void put(String key, Object value) {
			getResponse().setHeader(key, JUtil.toString(value));
		}

		/**
		 * 从 Response 中获取数据
		 */
		public static Object get(String key) {
			return getResponse().getHeader(key);
		}

		/**
		 * 从 Response 中获取所有数据
		 */
		public static Map<String, Object> getAll() {
			Map<String, Object> map = new HashMap<String, Object>();
			for (String name : getResponse().getHeaderNames()) {
				map.put(name, getResponse().getHeader(name));
			}
			return map;
		}
	}

	/**
	 * 封装 Session 相关操作
	 */
	public static class Session {

		/**
		 * 将数据放入 Session 中
		 */
		public static void put(String key, Object value) {
			getSession().setAttribute(key, value);
		}

		/**
		 * 从 Session 中获取数据
		 */
		public static Object get(String key) {
			return getSession().getAttribute(key);
		}

		/**
		 * 移除 Session 中的数据
		 */
		public static void remove(String key) {
			getSession().removeAttribute(key);
		}

		/**
		 * 从 Session 中获取所有数据
		 */
		public static Map<String, Object> getAll() {
			Map<String, Object> map = new HashMap<String, Object>();
			Enumeration<String> names = getSession().getAttributeNames();
			while (names.hasMoreElements()) {
				String name = names.nextElement();
				map.put(name, getSession().getAttribute(name));
			}
			return map;
		}

		/**
		 * 移除 Session 中所有的数据
		 */
		public static void removeAll() {
			getSession().invalidate();
		}
	}

	/**
	 * 封装 Cookie 相关操作
	 */
	public static class Cookie {

		/**
		 * 将数据放入 Cookie 中
		 */
		public static void put(String key, Object value) throws UnsupportedEncodingException {
			String strValue = URLEncoder.encode(JUtil.toString(value), CHARSET);
			javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(key, strValue);
			getResponse().addCookie(cookie);
		}

		/**
		 * 从 Cookie 中获取数据
		 */
		public static String get(String key) throws UnsupportedEncodingException {
			String value = null;
			javax.servlet.http.Cookie[] cookieArray = getRequest().getCookies();
			if (cookieArray != null) {
				for (javax.servlet.http.Cookie cookie : cookieArray) {
					if (key.equals(cookie.getName())) {
						value = URLDecoder.decode(cookie.getValue(), CHARSET);
						break;
					}
				}
			}
			return value;
		}

		/**
		 * 从 Cookie 中获取所有数据
		 */
		public static Map<String, Object> getAll() {
			Map<String, Object> map = new HashMap<String, Object>();
			javax.servlet.http.Cookie[] cookieArray = getRequest().getCookies();
			if (cookieArray != null) {
				for (javax.servlet.http.Cookie cookie : cookieArray) {
					map.put(cookie.getName(), cookie.getValue());
				}
			}
			return map;
		}
	}

	/**
	 * 封装 ServletContext 相关操作
	 */
	public static class ServletContext {

		/**
		 * 将数据放入 ServletContext 中
		 */
		public static void put(String key, Object value) {
			getServletContext().setAttribute(key, value);
		}

		/**
		 * 从 ServletContext 中获取数据
		 */
		public static Object get(String key) {
			return getServletContext().getAttribute(key);
		}

		/**
		 * 移除 ServletContext 中的数据
		 */
		public static void remove(String key) {
			getServletContext().removeAttribute(key);
		}

		/**
		 * 从 ServletContext 中获取所有数据
		 */
		public static Map<String, Object> getAll() {
			Map<String, Object> map = new HashMap<String, Object>();
			Enumeration<String> names = getServletContext().getAttributeNames();
			while (names.hasMoreElements()) {
				String name = names.nextElement();
				map.put(name, getServletContext().getAttribute(name));
			}
			return map;
		}
	}
}
